package com.example.inventoryservice.service;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.pattern.Patterns;
import akka.persistence.query.PersistenceQuery;
import akka.persistence.query.journal.leveldb.javadsl.LeveldbReadJournal;
import akka.persistence.query.journal.leveldb.javadsl.LeveldbReadJournal$;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Sink;
import akka.util.Timeout;
import com.example.inventoryservice.actor.PersistentInventoryActor;
import com.example.inventoryservice.event.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CompletableFuture;

/**
 * 库存事件查询服务
 * 提供库存事件溯源查询功能
 */
@Slf4j
@Service
public class InventoryEventQueryService {
    
    @Autowired
    private ActorSystem actorSystem;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    private final Timeout timeout = Timeout.create(Duration.ofSeconds(10));
    private final Materializer materializer = ActorMaterializer.create(actorSystem);
    
    /**
     * 查询指定订单的库存事件
     */
    public CompletionStage<List<InventoryEvent>> getInventoryEventsForOrder(String orderId) {
        log.info("查询订单库存事件: {}", orderId);
        
        try {
            // 创建 Actor 来查询事件
            ActorRef inventoryActor = actorSystem.actorOf(PersistentInventoryActor.props(), "inventory-" + orderId);
            
            // 使用 Akka Persistence Query 查询事件
            LeveldbReadJournal readJournal = PersistenceQuery.get(actorSystem)
                .getReadJournalFor(LeveldbReadJournal.class, LeveldbReadJournal.Identifier());
            
            String persistenceId = "inventory-" + orderId;
            
            return readJournal
                .eventsByPersistenceId(persistenceId, 0L, Long.MAX_VALUE)
                .map(envelope -> {
                    try {
                        // 将事件转换为 InventoryEvent
                        Object event = envelope.event();
                        if (event instanceof InventoryReservedEvent) {
                            return new InventoryEvent("RESERVED", (InventoryReservedEvent) event);
                        } else if (event instanceof InventoryConfirmedEvent) {
                            return new InventoryEvent("CONFIRMED", (InventoryConfirmedEvent) event);
                        } else if (event instanceof InventoryReleasedEvent) {
                            return new InventoryEvent("RELEASED", (InventoryReleasedEvent) event);
                        }
                        return null;
                    } catch (Exception e) {
                        log.error("解析库存事件失败: {}", e.getMessage(), e);
                        return null;
                    }
                })
                .filter(event -> event != null)
                .runWith(Sink.seq(), materializer)
                .thenApply(events -> {
                    List<InventoryEvent> eventList = new ArrayList<>();
                    events.forEach(eventList::add);
                    log.info("查询到 {} 个库存事件", eventList.size());
                    return eventList;
                });
                
        } catch (Exception e) {
            log.error("查询库存事件失败: {}", e.getMessage(), e);
            return CompletableFuture.completedFuture(new ArrayList<>());
        }
    }
    
    /**
     * 重建库存状态
     */
    public CompletionStage<PersistentInventoryActor.InventoryState> rebuildInventoryState() {
        log.info("重建库存状态");
        
        try {
            ActorRef inventoryActor = actorSystem.actorOf(PersistentInventoryActor.props(), "inventory-manager");
            
            PersistentInventoryActor.GetInventoryStatus getStatusCmd = new PersistentInventoryActor.GetInventoryStatus();
            
            return Patterns.ask(inventoryActor, getStatusCmd, timeout)
                .thenApply(response -> {
                    PersistentInventoryActor.InventoryStatus result = (PersistentInventoryActor.InventoryStatus) response;
                    // 这里需要从 status 中重建 InventoryState
                    // 简化实现，返回一个新的状态对象
                    return new PersistentInventoryActor.InventoryState();
                });
                
        } catch (Exception e) {
            log.error("重建库存状态失败: {}", e.getMessage(), e);
            return CompletableFuture.completedFuture(new PersistentInventoryActor.InventoryState());
        }
    }
    
    /**
     * 查询所有库存变更历史
     */
    public CompletionStage<List<InventoryChangeHistory>> getAllInventoryChanges() {
        log.info("查询所有库存变更历史");
        
        try {
            // 这里可以实现更复杂的查询逻辑
            // 例如：查询所有库存相关事件，构建变更历史
            return CompletableFuture.completedFuture(new ArrayList<>());
            
        } catch (Exception e) {
            log.error("查询库存变更历史失败: {}", e.getMessage(), e);
            return CompletableFuture.completedFuture(new ArrayList<>());
        }
    }
    
    /**
     * 库存事件包装类
     */
    public static class InventoryEvent {
        private String eventType;
        private Object eventData;
        
        public InventoryEvent() {}
        
        public InventoryEvent(String eventType, Object eventData) {
            this.eventType = eventType;
            this.eventData = eventData;
        }
        
        public String getEventType() { return eventType; }
        public void setEventType(String eventType) { this.eventType = eventType; }
        
        public Object getEventData() { return eventData; }
        public void setEventData(Object eventData) { this.eventData = eventData; }
    }
    
    /**
     * 库存变更历史类
     */
    public static class InventoryChangeHistory {
        private String orderId;
        private String eventType;
        private String productId;
        private Integer quantityChange;
        private String timestamp;
        
        public InventoryChangeHistory() {}
        
        public InventoryChangeHistory(String orderId, String eventType, String productId, Integer quantityChange, String timestamp) {
            this.orderId = orderId;
            this.eventType = eventType;
            this.productId = productId;
            this.quantityChange = quantityChange;
            this.timestamp = timestamp;
        }
        
        // Getters and Setters
        public String getOrderId() { return orderId; }
        public void setOrderId(String orderId) { this.orderId = orderId; }
        
        public String getEventType() { return eventType; }
        public void setEventType(String eventType) { this.eventType = eventType; }
        
        public String getProductId() { return productId; }
        public void setProductId(String productId) { this.productId = productId; }
        
        public Integer getQuantityChange() { return quantityChange; }
        public void setQuantityChange(Integer quantityChange) { this.quantityChange = quantityChange; }
        
        public String getTimestamp() { return timestamp; }
        public void setTimestamp(String timestamp) { this.timestamp = timestamp; }
    }
}
